嗨嗨大家~
昨天我們講到模型訓練的整個流程中,其實有非常多地方是我們可以選擇、優化的。
像是昨天提到的切分訓練集跟測試集就可以再多一步做交叉驗證,目的就是檢查模型的泛化能力。
那當然,在特徵選擇上也還有很多可以說的地方,今天我們就要來介紹一個在特徵表示中很常見的方法:將文字轉換成一袋詞(Bag Of Words, BoW)
不知道大家還記不記得,前幾週我們在訓練模型時有提到電腦看不懂文字,我們會需要把文字先轉換成數值他才看得懂,當時用的方式使用套件裡面的labelencoder
轉換,不過 LabelEncoder
主要是針對「標籤」來做轉換,那如果今天我們要處理的不是標籤,而是整段文字內容呢?例如一篇文章、使用者的留言,或是新聞標題,這些都不是單一的標籤,而是由很多字詞組成的文本。這時候,就需要一種方法,把「文字資料」也轉換成「數字特徵」,讓模型能夠讀懂並進行訓練。那今天要介紹的這個BoW 就是一種方法啦!
在介紹之前,我們要先釐清type 以及token 的概念
Token就是斷詞後的每一個詞彙。例如句子「我/喜歡/你/你/也/喜歡/我」,總共有 7 個 token 。
Type的話可以把它想成「詞的種類數」。也就是計算斷詞結果中有多少不同的詞。在剛剛的例子裡,出現的詞只有「我、喜歡、你、也」,所以 type 的數量是 4。
Token (斷詞結果) | Type (詞的種類) |
---|---|
我 | 我 |
喜歡 | 喜歡 |
你 | 你 |
你 | 也 |
也 | |
喜歡 | |
我 |
而 Bag of Words,就是把文本裡出現的 type 都收集起來,形成一個詞彙表,在之後,每一篇文章或每一句話就會依照這個詞彙表,轉換成一個向量,這個向量的每一個位置都代表詞彙表中的某個詞,值則是該詞在文本中是否有出現(如果沒有出現就會是0)。
我們舉個例子讓大家更好懂一些
假設我們現在有兩個句子a,b (斜線代表斷詞結果)
a. 你/喜歡/我
b. 我/喜歡/吃/蝦子
這兩句話的詞彙表裡面有的詞就會是:你,喜歡,我,吃,蝦子
而這兩句話表示成向量就會是:
a.[1,1,1,0,0]
b.[0,1,1,1,1]
a句的最後兩個值是0因為吃
、蝦子
並沒有出現在句子中,而b句的第一個值為0是因為你
並沒有出現在句子中,透過這種方式就可以最簡單的轉換文字給電腦理解啦~
雖然 Bag of Words 很直觀、簡單,但也有一些些小限制跟缺點:
維度爆炸(Curse of Dimensionality) 的問題:
大家可以看看,我們上面舉例的 a、b 兩個句子總共有 6 個 type,所以它們的向量維度就是 6。
但是,如果今天我們的文本量非常大,總共有上千甚至上萬個詞,那麼每一個句子就必須轉換成一個「上千維甚至上萬維」的向量,這樣會導致電腦有很大的負擔
向量稀疏的問題:
大家可以想一下,如果我今天的句子是:我 / 吃
而整個詞袋裡可能有 10 個 type,像是:我, 喜歡, 你, 也, 吃, 玩, 去, 跑, 睡, 看
那這個句子轉換成向量後就會變成:[1, 0, 0, 0, 1, 0, 0, 0, 0, 0]
可以看到,雖然我們有 10 維的向量,但其實只有兩個位置是 1,其他全部都是 0,如果詞袋規模再放大到幾千幾萬個詞,那每一個句子裡真正用到的詞通常只佔很少一部分,這樣就會導致整個向量大多數都是 0,變得非常稀疏,電腦在運算時也會很耗費資源
無法表達語意
再來最後一點就是這個作法會忽略詞序,沒辦法表達出真正的語意:
例如「我喜歡你」跟「你喜歡我」在這邊的向量會ㄧ模ㄧ樣,電腦會覺得他們是相同的東西,但其實他們的語意是完全不同的,而又時候語意對我們的任務來說是重要的,那用這個方式就會遇到一些問題。
因為這些問題,所以後續很多人用了不同的解決辦法,像是使用我們前幾週有說到的TF-IDF等,如果後續有機會再跟大家介紹更多!
好啦~~以上就是對於Bag Of Words的基本介紹, 一種常見將文字轉為數值並可以作為機器學習的特徵之一的方法,我們明天見啦!